// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

// 预编译指令，确保头文件只被包含一次

#include "ActiveGameplayEffectHandle.h"
#include "Engine/DataAsset.h"
#include "AttributeSet.h"
#include "GameplayTagContainer.h"

#include "GameplayAbilitySpecHandle.h"
#include "LyraAbilitySet.generated.h"

// 前置声明，减少编译依赖
class UAttributeSet;
class UGameplayEffect;
class ULyraAbilitySystemComponent;
class ULyraGameplayAbility;
class UObject;

/**
 * FLyraAbilitySet_GameplayAbility
 *
 *	能力集用于授予游戏能力的数据结构
 */
USTRUCT(BlueprintType)  // 标记为可在蓝图中使用的结构体
struct FLyraAbilitySet_GameplayAbility
{
    GENERATED_BODY()  // UE4宏，生成结构体所需代码

public:
    // 要授予的游戏能力类
    UPROPERTY(EditDefaultsOnly)  // 仅在编辑器中可编辑默认值
    TSubclassOf<ULyraGameplayAbility> Ability = nullptr;

    // 授予的能力等级
    UPROPERTY(EditDefaultsOnly)
    int32 AbilityLevel = 1;

    // 用于处理能力输入的标签
    UPROPERTY(EditDefaultsOnly, Meta = (Categories = "InputTag"))
    FGameplayTag InputTag;
};

/**
 * FLyraAbilitySet_GameplayEffect
 *
 *	能力集用于授予游戏效果的数据结构
 */
USTRUCT(BlueprintType)
struct FLyraAbilitySet_GameplayEffect
{
    GENERATED_BODY()

public:
    // 要授予的游戏效果类
    UPROPERTY(EditDefaultsOnly)
    TSubclassOf<UGameplayEffect> GameplayEffect = nullptr;

    // 授予的效果等级
    UPROPERTY(EditDefaultsOnly)
    float EffectLevel = 1.0f;
};

/**
 * FLyraAbilitySet_AttributeSet
 *
 *	能力集用于授予属性集的数据结构
 */
USTRUCT(BlueprintType)
struct FLyraAbilitySet_AttributeSet
{
    GENERATED_BODY()

public:
    // 要授予的属性集类
    UPROPERTY(EditDefaultsOnly)
    TSubclassOf<UAttributeSet> AttributeSet;
};

/**
 * FLyraAbilitySet_GrantedHandles
 *
 *	用于存储能力集已授予内容句柄的数据结构
 */
USTRUCT(BlueprintType)
struct FLyraAbilitySet_GrantedHandles
{
    GENERATED_BODY()

public:
    // 添加能力规格句柄
    void AddAbilitySpecHandle(const FGameplayAbilitySpecHandle& Handle);
    
    // 添加游戏效果句柄
    void AddGameplayEffectHandle(const FActiveGameplayEffectHandle& Handle);
    
    // 添加属性集
    void AddAttributeSet(UAttributeSet* Set);

    // 从能力系统组件中移除所有已授予的内容
    void TakeFromAbilitySystem(ULyraAbilitySystemComponent* LyraASC);

protected:
    // 已授予能力的句柄数组
    UPROPERTY()
    TArray<FGameplayAbilitySpecHandle> AbilitySpecHandles;

    // 已授予游戏效果的句柄数组
    UPROPERTY()
    TArray<FActiveGameplayEffectHandle> GameplayEffectHandles;

    // 已授予属性集的指针数组
    UPROPERTY()
    TArray<TObjectPtr<UAttributeSet>> GrantedAttributeSets;
};

/**
 * ULyraAbilitySet
 *
 *	不可变的数据资产，用于授予游戏能力和游戏效果
 */
UCLASS(BlueprintType, Const)  // 标记为可在蓝图中使用的常量类
class ULyraAbilitySet : public UPrimaryDataAsset  // 继承自主数据资产
{
    GENERATED_BODY()

public:
    // 构造函数
    ULyraAbilitySet(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

    // 将能力集授予指定的能力系统组件
    // 返回的句柄可用于后续移除已授予的内容
    void GiveToAbilitySystem(ULyraAbilitySystemComponent* LyraASC, FLyraAbilitySet_GrantedHandles* OutGrantedHandles, UObject* SourceObject = nullptr) const;

protected:
    // 当此能力集被授予时要授予的游戏能力数组
    UPROPERTY(EditDefaultsOnly, Category = "Gameplay Abilities", meta=(TitleProperty=Ability))
    TArray<FLyraAbilitySet_GameplayAbility> GrantedGameplayAbilities;

    // 当此能力集被授予时要授予的游戏效果数组
    UPROPERTY(EditDefaultsOnly, Category = "Gameplay Effects", meta=(TitleProperty=GameplayEffect))
    TArray<FLyraAbilitySet_GameplayEffect> GrantedGameplayEffects;

    // 当此能力集被授予时要授予的属性集数组
    UPROPERTY(EditDefaultsOnly, Category = "Attribute Sets", meta=(TitleProperty=AttributeSet))
    TArray<FLyraAbilitySet_AttributeSet> GrantedAttributes;
};